/* $Id: Svga.h $ */
/** @file
 * VirtualBox Windows Guest Mesa3D - Gallium driver VMSVGA.
 */

/*
 * Copyright (C) 2016-2020 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 */

#ifndef _WDDM_INCLUDE_GALLIUM_SVGA_H_
#define _WDDM_INCLUDE_GALLIUM_SVGA_H_

#include <ntddk.h>
#include <dispmprt.h>

#include "Common/VBoxMPIf.h"
#include "CommonDef.h"
#include "gallium/VBoxMPGaUtils.h"
#include "list.h"
#include "VBoxGaHWSVGA.h"
#include "avl.h"

 /* VMSVGA headers. */
#pragma pack(1) /* VMSVGA structures are '__packed'. */
#include "svga_reg.h"
#include "svga3d_reg.h"
#pragma pack()

#define SVGA_RESOLUTION_EVENT L"\\BaseNamedObjects\\SvgaResolutionEvent"

#define SVGA_SYNC_GENERIC         1
#define SVGA_SYNC_FIFOFULL        2

typedef struct VMSVGAFIFO
{
    /** SVGA_FIFO_CAPABILITIES */
    UINT32 u32FifoCaps;

    /** How many bytes were reserved for a command. */
    UINT32 cbReserved;

    /** Temporary buffer for commands crossing the FIFO ring boundary. */
    void *pvBuffer;

    /** FIFO access. */
    FAST_MUTEX FifoMutex;
} VMSVGAFIFO, *PVMSVGAFIFO;

/*
 * Command buffers.
 */
typedef struct VMSVGACBPAGE
{
    RTR0MEMOBJ           hMemObjPages;
    RTR0MEMOBJ           hMemObjMapping;
    RTR0PTR              pvR0;
    RTHCPHYS             PhysAddr;
    UINT32               useMiniportPool;
    UINT32               miniportPoolIndex;
} VMSVGACBPAGE, *PVMSVGACBPAGE;

typedef UINT32 VMSVGACBHEADERHANDLE;
#define VMSVGACBHEADER_NIL (-1)

struct VBOXWDDM_EXT_VMSVGA;
typedef void (*PFNCBCOMPLETION)(struct VBOXWDDM_EXT_VMSVGA *pSvga, void *pvData, UINT32 cbData);
typedef struct VMSVGACBCOMPLETION
{
    RTLISTNODE                  nodeCompletion;             /* VMSVGACB::listCompletion */
    PFNCBCOMPLETION             pfn;                        /* Function to call. */
    UINT32                      cb;                         /* Size of data in bytes. */
    /* cb bytes follow. */
} VMSVGACBCOMPLETION, *PVMSVGACBCOMPLETION;

typedef enum VMSVGACBTYPE
{
    VMSVGACB_INVALID = 0,
    VMSVGACB_CONTEXT_DEVICE = 1,                   /* SVGA_CB_CONTEXT_DEVICE commands. */
    VMSVGACB_MINIPORT = 2,                         /* Commands generated by the miniport. */
    VMSVGACB_UMD = 3                               /* WDDM DMA buffer. */
} VMSVGACBTYPE;

/* Information about a command buffer. */
typedef struct VMSVGACB
{
    RTLISTNODE           nodeQueue;                /* For a queue where the buffer is currently resides. */
    VMSVGACBTYPE         enmType;                  /* Type of the buffer. */
    UINT32               idDXContext;              /* DX context of the buffer or SVGA3D_INVALID_ID. */
    UINT32               cbBuffer;                 /* Total size. */
    UINT32               cbCommand;                /* Size of commands. */
    UINT32               cbReservedCmdHeader;      /* Reserved for the command header. */
    UINT32               cbReservedCmd;            /* Reserved for the current command without the header. */
    UINT32               u32ReservedCmd;           /* The current command. */
    VMSVGACBHEADERHANDLE hHeader;                  /* Handle of the header (index in the header pool array). */
    SVGACBHeader        *pCBHeader;                /* Pointer to the header. */
    PHYSICAL_ADDRESS     CBHeaderPhysAddr;
    union                                          /* Command data. */
    {
        PVMSVGACBPAGE     page;                     /* VMSVGACB_CONTEXT_DEVICE and VMSVGACB_MINIPORT */
        PHYSICAL_ADDRESS DmaBufferPhysicalAddress; /* VMSVGACB_UMD */
    } commands;
    RTLISTANCHOR         listCompletion;           /* VMSVGACBCOMPLETION to be called on completion. */
#ifdef DEBUG
    bool fSubmitted : 1;
#endif
} VMSVGACB, *PVMSVGACB;

/* Buffer headers are allocated for submitted buffers, which sometimes are not immediately passed to the host.
 * Therefore the pool must be a bit larger than SVGA_CB_MAX_QUEUED_PER_CONTEXT * SVGA_CB_CONTEXT_MAX
 */
#define VMSVGA_CB_HEADER_POOL_NUM_PAGES         2
#define VMSVGA_CB_HEADER_POOL_HANDLES_PER_PAGE (PAGE_SIZE / sizeof(SVGACBHeader))
#define VMSVGA_CB_HEADER_POOL_NUM_HANDLES      (VMSVGA_CB_HEADER_POOL_NUM_PAGES * VMSVGA_CB_HEADER_POOL_HANDLES_PER_PAGE)

typedef struct VMSVGACBHEADERPOOL
{
    KSPIN_LOCK           SpinLock;
    VMSVGACBPAGE         aHeaderPoolPages[VMSVGA_CB_HEADER_POOL_NUM_PAGES];
    UINT32               au32HeaderBits[VMSVGA_CB_HEADER_POOL_NUM_HANDLES / 32];
} VMSVGACBHEADERPOOL, *PVMSVGACBHEADERPOOL;

#define VMSVGA_CB_MINIPORT_NUM_PAGES         256
typedef struct VMSVGACBMINIPORTPOOL
{
    KSPIN_LOCK           SpinLock;
    VMSVGACBPAGE         aMiniportPoolPages[VMSVGA_CB_MINIPORT_NUM_PAGES];
    UINT32               au32MiniportBits[VMSVGA_CB_MINIPORT_NUM_PAGES / 32];
} VMSVGACBMINIPORTPOOL, *PVMSVGACBMINIPORTPOOL;

typedef struct VMSVGACBCONTEXT
{
    RTLISTANCHOR         QueuePending;             /* Buffers which will be submitted to the host. */
    RTLISTANCHOR         QueueSubmitted;           /* Buffers which are being processed by the host. */
    UINT32               cSubmitted;               /* How many buffers were submitted to the host.
                                                    * Less than SVGA_CB_MAX_QUEUED_PER_CONTEXT */
} VMSVGACBCONTEXT, *PVMSVGACBCONTEXT;

typedef struct VMSVGACBSTATE
{
    VMSVGACBCONTEXT      aCBContexts[SVGA_CB_CONTEXT_MAX]; /* Command buffer contexts. */
    VMSVGACBHEADERPOOL   HeaderPool;               /* Array of buffer headers. */
    VMSVGACBMINIPORTPOOL MiniportPool;
    PVMSVGACB            pCBCurrent;               /* Current buffer for miniport commands. */
    FAST_MUTEX           CBCurrentMutex;           /* Access pCBCurrent. */
    KSPIN_LOCK           SpinLock;                 /* Lock for aCBContexts. */
} VMSVGACBSTATE, *PVMSVGACBSTATE;

/* Guest Backed Object: a set of locked pages and a page table for the host to access. */
typedef struct VMSVGAGBO
{
    UINT32                      cbGbo;                      /* Size of gbo in bytes. */
    UINT32                      cPTPages;                   /* How many pages are required to hold PPN64 page table. */
    SVGAMobFormat               enmMobFormat;               /* Page table format. */
    PPN64                       base;                       /* Page which contains the page table. */
    RTR0MEMOBJ                  hMemObjPT;                  /* Page table pages. */
} VMSVGAGBO, *PVMSVGAGBO;

/* Contexts + One shaders mob per context + surfaces. */
#define SVGA3D_MAX_MOBS (SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_SURFACE_IDS)

/* Dxva Decoder Id manage */
#define VMSVGA_DXDECODER_ID_MAX 64

/* Memory OBject: a gbo with an id, possibly bound to an allocation. */
typedef struct VMSVGAMOB
{
    UINT32                      mobId;                      /* Memory object id, index of MobTree to find instance pointer */
    HANDLE                      hAllocation;                /* Allocation which is bound to the mob. */
    VMSVGAGBO                   gbo;                        /* Gbo for this mob. */
    RTR0MEMOBJ                  hMemObj;                    /* The guest memory if allocated by miniport. */
    UINT32                      u64MobFence;                /* Free by the guest when the host reports this fence value. */
    RTLISTNODE                  node;                       /* VBOXWDDM_EXT_VMSVGA::listMobDeferredDestruction */
} VMSVGAMOB, *PVMSVGAMOB;

#define VMSVGAMOB_ID(a_pMob) ((a_pMob)->mobId)

typedef struct VMSVGAOT
{
    VMSVGAGBO                   gbo;
    RTR0MEMOBJ                  hMemObj;
    UINT32                      cEntries;                   /* How many objects can be stored in the OTable. */
} VMSVGAOT, *PVMSVGAOT;

struct GAWDDMREGION;

/* VMSVGA specific part of Gallium device extension. */
typedef struct VBOXWDDM_EXT_VMSVGA
{
    /** First IO port. SVGA_*_PORT are relative to it. */
    RTIOPORT ioportBase;
    /** Pointer to FIFO MMIO region. */
    volatile UINT32* pu32FIFO;
    volatile UINT32* pu32SysIO;

    /**
     * Hardware capabilities.
     */
    UINT32 u32Caps;         /** SVGA_REG_CAPABILITIES */
    UINT32 u32VramSize;     /** SVGA_REG_VRAM_SIZE */
    UINT32 u32FifoSize;     /** SVGA_REG_MEM_SIZE */
    UINT32 u32MaxWidth;     /** SVGA_REG_MAX_WIDTH */
    UINT32 u32MaxHeight;    /** SVGA_REG_MAX_HEIGHT */
    UINT32 u32GmrMaxIds;    /** SVGA_REG_GMR_MAX_IDS */
    UINT32 u32GmrMaxPages;  /** SVGA_REG_GMRS_MAX_PAGES */
    UINT32 u32MemorySize;   /** SVGA_REG_MEMORY_SIZE */
    /** Fifo state. */
    VMSVGAFIFO fifo;

    /** Command buffers state. */
    PVMSVGACBSTATE pCBState;
    /** Whether the host has generated an IRQ for buffer completion or error. */
    bool volatile fCommandBufferIrq;

    bool volatile fConfigIrq;

    UINT32 u32MaxTextureLevels; /** 1 + floor(log2(max(u32MaxTextureWidth, u32MaxTextureHeight))) */

    /** Maintaining the host objects lists. */
    KSPIN_LOCK HostObjectsSpinLock;
    KSPIN_LOCK GmrSpinLock;
    KSPIN_LOCK SurfaceSpinLock;
    KSPIN_LOCK ContextSpinLock;
    KSPIN_LOCK MobSpinLock;
    KSPIN_LOCK DxContextSpinLock;
    KSPIN_LOCK CapSpinLock;
    KSPIN_LOCK DecoderSpinLock;

    /** For atomic hardware access. */
    KSPIN_LOCK HwSpinLock;

    /** SVGA data access. */
    FAST_MUTEX SvgaMutex;

    GAWDDMREGION **GMRArray; /* pointer array */

    /** AVL tree for mapping sids to the surface objects. */
    AVLU32TREE SurfaceTree;

    PVMSVGAMOB *MobTree; /*  Mob array */

    struct
    {
        UINT32 u32Offset;
        UINT32 u32BytesPerLine;
    } lastGMRFB;

    VMSVGAOT aOT[SVGA_OTABLE_DX_MAX];

    PVMSVGAMOB pMiniportMob; /* Used by miniport to communicate with the device. */
    struct VMSVGAMINIPORTMOB volatile* pMiniportMobData; /* Pointer to the miniport mob content. */

    UINT64 volatile u64MobFence;
    RTLISTANCHOR listMobDeferredDestruction; /* Mob to be deleted after. */

    /** Bitmap of used GMR ids. Bit 0 - GMR id 0, etc. */
    UINT32 *pu32GMRBits; /* Number of GMRs is controlled by the host (u32GmrMaxIds), so allocate the bitmap. */
    UINT32 cbGMRBits;    /* Bytes allocated for pu32GMRBits */

    /** List of host objects, which must be deleted at PASSIVE_LEVEL. */
    RTLISTANCHOR DeletedHostObjectsList;

    /** Bitmap of used context ids. Bit 0 - context id 0, etc. */
    UINT32 au32ContextBits[(SVGA3D_MAX_CONTEXT_IDS + 31) / 32];
    /** Bitmap of used surface ids. Bit 0 - surface id 0, etc. */
    UINT32 au32SurfaceBits[(SVGA3D_MAX_SURFACE_IDS + 31) / 32];

    /** Bitmap of used DX context ids. Bit 0 - context id 0, etc. */
    UINT32 au32DXContextBits[(SVGA3D_MAX_CONTEXT_IDS + 31) / 32];

    /** Bitmap of used MOB ids. Bit 0 - context id 0, etc. */
    UINT32 au32MobBits[(SVGA3D_MAX_MOBS + 31) / 32];

    /** Bitmap of used Decoder ids. Bit 0 - decoder id 0, etc. */
    UINT32 au32DecoderBits[(VMSVGA_DXDECODER_ID_MAX + 31) / 32];

    PKEVENT ResolutionEvent;
    HANDLE ResolutionEventHandle;

    /* Number of async work in processing */
    UINT32 asyncWorkCount;
    /* Memory Statistics. */
    UINT32 volatile cAllocatedGmrs;
    UINT32 volatile cAllocatedGmrPages;
} VBOXWDDM_EXT_VMSVGA, *PVBOXWDDM_EXT_VMSVGA;

typedef struct VMSVGAMINIPORTMOB
{
    UINT64 u64MobFence; /* Host writes SVGA3dCmdDXMobFence64::value here. */
} VMSVGAMINIPORTMOB;

typedef struct VMSVGACOT
{
    PVMSVGAMOB              pMob;                       /* COTable mob. */
    UINT32                  cEntries;                   /* How many objects can be stored in the COTable. */
} VMSVGACOT, *PVMSVGACOT;

typedef struct VMSVGACONTEXT
{
    UINT32                      u32Cid;                     /* SVGA context id of this context. */
    bool                        fDXContext : 1;             /* Whether this context is a DX context or VGPU9. */
    bool                        fDebugVerifyCommands : 1;
    VMSVGACOT                   aCOT[SVGA_COTABLE_MAX];     /* Context Object Tables. */
} VMSVGACONTEXT, *PVMSVGACONTEXT;

#define SVGA_HOST_OBJECT_UNDEFINED 0
#define SVGA_HOST_OBJECT_SURFACE   1

typedef NTSTATUS FNHostObjectDestroy(struct SVGAHOSTOBJECT *pThis);
typedef FNHostObjectDestroy *PFNHostObjectDestroy;

/* Information about an allocated surface. */
typedef struct SVGAHOSTOBJECT
{
    union {
        /* core.Key is the object id: surface id (sid), or (curently not required) context id (cid), gmr id (gid). */
        struct
        {
            AVLU32NODECORE core;
        } avl;

        struct {
            RTLISTNODE node;
            uint32_t u32Key;
        } list;
    } u;


    /* By UM driver, during submission of commands, by shared surface, etc. */
    UINT32 volatile cRefs;

    /* SVGA_HOST_OBJECT_ type. */
    UINT32 uType;

    /* Device the object is associated with. */
    VBOXWDDM_EXT_VMSVGA *pSvga;

    /* Destructor. */
    PFNHostObjectDestroy pfnHostObjectDestroy;
} SVGAHOSTOBJECT;

#define SVGAHOSTOBJECTID(pHO) ((pHO)->u.avl.core.Key)

/* Information about an allocated surface. */
typedef struct SURFACEOBJECT
{
    SVGAHOSTOBJECT ho;

    /* The actual sid, which must be used by the commands instead of the ho.core.Key.
     * Equal to the AVL node key for non-shared surfaces.
     */
    UINT32 u32SharedSid;
    UINT32 mobid;
} SURFACEOBJECT;

typedef struct GAHWRENDERDATA
{
    RTLISTNODE node;
    UINT32 u32SubmissionFenceId;
    UINT32 u32Reserved;
} GAHWRENDERDATA;

DECLINLINE(void) SvgaHostObjectsLock(VBOXWDDM_EXT_VMSVGA *pSvga, KIRQL *pOldIrql)
{
    KeAcquireSpinLock(&pSvga->HostObjectsSpinLock, pOldIrql);
}

DECLINLINE(void) SvgaHostObjectsUnlock(VBOXWDDM_EXT_VMSVGA *pSvga, KIRQL OldIrql)
{
    KeReleaseSpinLock(&pSvga->HostObjectsSpinLock, OldIrql);
}

NTSTATUS SvgaSurfaceDestroy(PVBOXWDDM_EXT_VMSVGA pSvga,
                            UINT32 u32Sid);
NTSTATUS SvgaSurfaceIdFree(PVBOXWDDM_EXT_VMSVGA pSvga,
                           UINT32 u32Sid);
NTSTATUS SvgaSurfaceIdAlloc(PVBOXWDDM_EXT_VMSVGA pSvga,
                            UINT32 *pu32Sid);
NTSTATUS SvgaSurfaceDefine(PVBOXWDDM_EXT_VMSVGA pSvga,
                           GASURFCREATE const *pCreateParms,
                           GASURFSIZE const *paSizes,
                           UINT32 cSizes,
                           UINT32 u32Sid);

NTSTATUS SvgaAdapterStart(PVBOXWDDM_EXT_VMSVGA *ppSvga,
                          DXGKRNL_INTERFACE *pDxgkInterface,
                          PHYSICAL_ADDRESS physFIFO,
                          ULONG cbFIFO,
                          PHYSICAL_ADDRESS physIO,
                          ULONG cbIO);
void SvgaAdapterStop(PVBOXWDDM_EXT_VMSVGA pSvga, DXGKRNL_INTERFACE *pDxgkInterface);
NTSTATUS SvgaDefineCursor(PVBOXWDDM_EXT_VMSVGA pSvga,
                          UINT32 u32HotspotX,
                          UINT32 u32HotspotY,
                          UINT32 u32Width,
                          UINT32 u32Height,
                          UINT32 u32AndMaskDepth,
                          UINT32 u32XorMaskDepth,
                          void const* pvAndMask,
                          UINT32 cbAndMask,
                          void const* pvXorMask,
                          UINT32 cbXorMask);
void SvgaUpdateCursorPosition(PVBOXWDDM_EXT_VMSVGA pSvga,
                              UINT32 u32Visible,
                              UINT32 u32HotspotX,
                              UINT32 u32HotspotY);
NTSTATUS SvgaDefineAlphaCursor(PVBOXWDDM_EXT_VMSVGA pSvga,
                               UINT32 u32HotspotX,
                               UINT32 u32HotspotY,
                               UINT32 u32Width,
                               UINT32 u32Height,
                               void const* pvImage,
                               UINT32 cbImage);
NTSTATUS SvgaScreenDefine(PVBOXWDDM_EXT_VMSVGA pSvga,
                          UINT32 u32Offset,
                          UINT32 u32ScreenId,
                          INT32 xOrigin,
                          INT32 yOrigin,
                          UINT32 u32Width,
                          UINT32 u32Height,
                          bool fBlank);
NTSTATUS SvgaScreenDestroy(PVBOXWDDM_EXT_VMSVGA pSvga,
                           UINT32 u32ScreenId);
NTSTATUS SvgaUpdate(PVBOXWDDM_EXT_VMSVGA pSvga,
                    UINT32 u32X,
                    UINT32 u32Y,
                    UINT32 u32Width,
                    UINT32 u32Height);
NTSTATUS SvgaContextIdAlloc(PVBOXWDDM_EXT_VMSVGA pSvga,
                            UINT32 *pu32Cid);
NTSTATUS SvgaContextIdFree(PVBOXWDDM_EXT_VMSVGA pSvga,
                           UINT32 u32Cid);
NTSTATUS SvgaContextCreate(PVBOXWDDM_EXT_VMSVGA pSvga,
                           UINT32 u32Cid);
NTSTATUS SvgaContextDestroy(PVBOXWDDM_EXT_VMSVGA pSvga,
                            UINT32 u32Cid);
NTSTATUS SvgaGenBlitSurfaceToScreen(PVBOXWDDM_EXT_VMSVGA pSvga,
    UINT32 sid, RECT const *pSrcRect, UINT32 idDstScreen, RECT const *pDstRect,
    UINT32 cDstClipRects, RECT const *paDstClipRects, void *pvDst,
    UINT32 cbDst, UINT32 *pcbOut, UINT32 *pcOutDstClipRects);
NTSTATUS SvgaGenDefineGMRFB(PVBOXWDDM_EXT_VMSVGA pSvga,
                            UINT32 u32Offset,
                            UINT32 u32BytesPerLine,
                            void *pvDst,
                            UINT32 cbDst,
                            UINT32 *pcbOut);
NTSTATUS SvgaGenBlitGMRFBToScreen(PVBOXWDDM_EXT_VMSVGA pSvga,
                                  UINT32 idDstScreen,
                                  UINT32 xSrc,
                                  UINT32 ySrc,
                                  RECT const *pDstRect,
                                  void *pvDst,
                                  UINT32 cbDst,
                                  UINT32 *pcbOut);
NTSTATUS SvgaGenBlitScreenToGMRFB(PVBOXWDDM_EXT_VMSVGA pSvga,
                                  UINT32 idSrcScreen,
                                  UINT32 xSrc,
                                  UINT32 ySrc,
                                  RECT const *pDstRect,
                                  void *pvDst,
                                  UINT32 cbDst,
                                  UINT32 *pcbOut);
NTSTATUS SvgaGenSurfaceDMA(PVBOXWDDM_EXT_VMSVGA pSvga,
                           SVGAGuestImage const *pGuestImage,
                           SVGA3dSurfaceImageId const *pSurfId,
                           SVGA3dTransferType enmTransferType, UINT32 xSrc, UINT32 ySrc,
                           UINT32 xDst, UINT32 yDst, UINT32 cWidth, UINT32 cHeight,
                           void *pvDst,
                           UINT32 cbDst,
                           UINT32 *pcbOut);
NTSTATUS SvgaGenSurfaceCopy(PVBOXWDDM_EXT_VMSVGA pSvga,
                            SVGA3dSurfaceImageId const *pSrcId,
                            SVGA3dSurfaceImageId const *pDstId,
                            UINT32 xSrc, UINT32 ySrc,
                            UINT32 xDst, UINT32 yDst, UINT32 cWidth, UINT32 cHeight,
                            void *pvDst,
                            UINT32 cbDst,
                            UINT32 *pcbOut);
NTSTATUS SvgaRenderCommands(PVBOXWDDM_EXT_VMSVGA pSvga,
                            struct VMSVGACONTEXT *pSvgaContext,
                            void *pvTarget,
                            UINT32 cbTarget,
                            const void *pvSource,
                            UINT32 cbSource,
                            UINT32 *pu32TargetLength,
                            UINT32 *pu32ProcessedLength,
                            GAHWRENDERDATA **ppHwRenderData);
NTSTATUS SvgaRenderComplete(PVBOXWDDM_EXT_VMSVGA pSvga,
                            GAHWRENDERDATA *pHwRenderData);
NTSTATUS SvgaSurfaceObjectRelease(SURFACEOBJECT *pSO);
SURFACEOBJECT *SvgaSurfaceObjectQuery(VBOXWDDM_EXT_VMSVGA *pSvga,
                                      UINT32 u32Sid);
NTSTATUS SvgaQueryInfo(PVBOXWDDM_EXT_VMSVGA pSvga,
                       VBOXGAHWINFOSVGA *pSvgaInfo);
NTSTATUS SvgaFence(PVBOXWDDM_EXT_VMSVGA pSvga, UINT32 u32Fence);
NTSTATUS SvgaHostObjectsCleanup(VBOXWDDM_EXT_VMSVGA *pSvga);
NTSTATUS SvgaRegionCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
                          void *pvOwner,
                          UINT32 u32NumPages,
                          UINT32 *pu32GmrId,
                          UINT64 *pu64UserAddress);
NTSTATUS SvgaRegionUserAddressAndSize(VBOXWDDM_EXT_VMSVGA *pSvga,
                                      UINT32 u32GmrId,
                                      UINT64 *pu64UserAddress,
                                      UINT32 *pu32Size);
NTSTATUS SvgaRegionDestroy(VBOXWDDM_EXT_VMSVGA *pSvga,
                           UINT32 u32GmrId);
void SvgaRegionsDestroy(VBOXWDDM_EXT_VMSVGA *pSvga,
                        void *pvOwner);
NTSTATUS SvgaPresentVRAM(PVBOXWDDM_EXT_VMSVGA pSvga,
                         UINT32 u32Sid,
                         UINT32 u32Width,
                         UINT32 u32Height,
                         UINT32 u32VRAMOffset);
NTSTATUS SvgaSurfaceCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
                           GASURFCREATE *pCreateParms,
                           GASURFSIZE *paSizes,
                           UINT32 cSizes,
                           UINT32 *pu32Sid);
NTSTATUS SvgaGBSurfaceCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
                             void *pvOwner,
                             SVGAGBSURFCREATE *pCreateParms);
NTSTATUS SvgaSurfaceUnref(VBOXWDDM_EXT_VMSVGA *pSvga,
                          UINT32 u32Sid);
NTSTATUS SvgaSharedSidRemove(VBOXWDDM_EXT_VMSVGA *pSvga,
                             UINT32 u32Sid);
NTSTATUS SvgaSharedSidInsert(VBOXWDDM_EXT_VMSVGA *pSvga,
                             UINT32 u32Sid,
                             UINT32 u32SharedSid);

NTSTATUS SvgaGboInit(VMSVGAGBO *pGbo, UINT32 cPages);
void SvgaGboFree(VMSVGAGBO *pGbo);
NTSTATUS SvgaGboFillPageTableForMDL(PVMSVGAGBO pGbo,
                                    PMDL pMdl,
                                    UINT32 MdlOffset);
NTSTATUS SvgaGboFillPageTableForMemObj(PVMSVGAGBO pGbo,
                                       RTR0MEMOBJ hMemObj);

void SvgaMobFree(VBOXWDDM_EXT_VMSVGA *pSvga,
                 PVMSVGAMOB pMob);
PVMSVGAMOB SvgaMobQuery(VBOXWDDM_EXT_VMSVGA *pSvga,
                        UINT32 mobid);
NTSTATUS SvgaMobCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
                       PVMSVGAMOB *ppMob,
                       UINT32 cMobPages,
                       HANDLE hAllocation);

NTSTATUS SvgaDXContextIdAlloc(PVBOXWDDM_EXT_VMSVGA pSvga,
                              UINT32 *pu32Cid);
NTSTATUS SvgaDXContextIdFree(PVBOXWDDM_EXT_VMSVGA pSvga,
                             UINT32 u32Cid);
NTSTATUS SvgaDXContextCreate(PVBOXWDDM_EXT_VMSVGA pSvga,
                             UINT32 u32Cid, CHAR *pAppName, UINT32 u32AppNameLen);
NTSTATUS SvgaDXContextDestroy(PVBOXWDDM_EXT_VMSVGA pSvga,
                              UINT32 u32Cid);

NTSTATUS SvgaRenderCommandsD3D(PVBOXWDDM_EXT_VMSVGA pSvga,
                               PVMSVGACONTEXT pSvgaContext,
                               void *pvTarget,
                               UINT32 cbTarget,
                               const void *pvSource,
                               UINT32 cbSource,
                               UINT32 *pu32TargetLength,
                               UINT32 *pu32ProcessedLength);
NTSTATUS SvgaMobSetMemObj(PVMSVGAMOB pMob,
                          RTR0MEMOBJ hMemObj);
NTSTATUS SvgaMobDestroy(VBOXWDDM_EXT_VMSVGA *pSvga,
                        PVMSVGAMOB pMob,
                        void *pvCmd,
                        UINT32 cbReserved,
                        UINT32 *pcbCmd);
NTSTATUS SvgaCOTNotifyId(VBOXWDDM_EXT_VMSVGA *pSvga,
                         PVMSVGACONTEXT pSvgaContext,
                         SVGACOTableType enmType,
                         UINT32 id);
NTSTATUS SvgaCreateDecoder(VBOXWDDM_EXT_VMSVGA *pSvga,
                           UINT32 pDecoderId,
                           VBoxVideoDecoderDesc *desc,
                           VBoxVideoDecoderConfigPic *pic,
                           UINT32 pCid);
NTSTATUS SvgaDestroyDecoder(VBOXWDDM_EXT_VMSVGA *pSvga,
                            UINT32 pu32DecoderId);
NTSTATUS SvgaSetDecoderRT(VBOXWDDM_EXT_VMSVGA *pSvga,
                          UINT32 pu32DecoderId,
                          UINT32 pu32Sid,
                          UINT32 pu32SubIndex);
NTSTATUS SvgaSetDecoderBeginFrame(VBOXWDDM_EXT_VMSVGA *pSvga,
                                  UINT32 pu32DecoderId);
NTSTATUS SvgaSetDecoderEndFrame(VBOXWDDM_EXT_VMSVGA *pSvga,
                                UINT32 pu32DecoderId);
NTSTATUS SvgaSetDecoderExecute(VBOXWDDM_EXT_VMSVGA *pSvga,
                               UINT32 pu32DecoderId,
                               UINT32 bufferCount,
                               VBOXDISPIFSCAPE_VIDEODECODERBUFFERDESC* bufferDesc);
NTSTATUS SvgaDecodeSurfaceInfo(VBOXWDDM_EXT_VMSVGA *pSvga,
                               UINT32 puSurfaceCount,
                               UINT32* surfaceInfo);
NTSTATUS SvgaStretchRetc(VBOXWDDM_EXT_VMSVGA *pSvga,
                         UINT32 uSrcSid,
                         UINT32 uDstSid,
                         RECT SrcRetc,
                         RECT DstRetc,
                         UINT32 u32Cid);

NTSTATUS svgaCreateMiniportMob(VBOXWDDM_EXT_VMSVGA *pSvga);
void SvgaRegionBindSurfaceId(VBOXWDDM_EXT_VMSVGA *pSvga, UINT32 gmrid, UINT32 u32Sid);
void SvgaRegionUnBindSurfaceId(VBOXWDDM_EXT_VMSVGA *pSvga, UINT32 gmrid, UINT32 u32Sid);
#endif
